package com.zbkj.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.api.R;
import com.zbkj.common.constants.*;
import com.zbkj.common.exception.CrmebException;
// 新加注释
//import com.zbkj.common.model.combination.StoreCombination;
//import com.zbkj.common.model.combination.StorePink;
import com.zbkj.common.model.Integral.IntegralParameter;
import com.zbkj.common.model.coupon.StoreCouponUser;
import com.zbkj.common.model.order.StoreOrder;
import com.zbkj.common.model.order.StoreOrderInfo;
import com.zbkj.common.model.product.StoreProductAttrValue;
import com.zbkj.common.model.product.StoreProductCoupon;
import com.zbkj.common.model.sms.SmsTemplate;
import com.zbkj.common.model.system.SystemAdmin;
import com.zbkj.common.model.system.SystemNotification;
import com.zbkj.common.model.system.SystemUserLevel;
import com.zbkj.common.model.user.*;
import com.zbkj.common.request.OrderPayRequest;
import com.zbkj.common.response.OrderPayResultResponse;
import com.zbkj.common.response.StoreProductResponse;
import com.zbkj.common.response.TopDetail;
import com.zbkj.common.utils.CrmebUtil;
import com.zbkj.common.utils.DateUtil;
import com.zbkj.common.utils.RedisUtil;
import com.zbkj.common.utils.WxPayUtil;
import com.zbkj.common.vo.*;
import com.zbkj.service.delete.OrderUtils;
import com.zbkj.service.service.*;
import com.zbkj.service.util.IntegralUtil;
import io.swagger.models.auth.In;
import lombok.Builder;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.apache.jasper.tagplugins.jstl.core.If;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;


/**
 * OrderPayService 实现类
 * +----------------------------------------------------------------------
 * | CRMEB [ CRMEB赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed CRMEB并不是自由软件，未经许可不能去掉CRMEB相关版权
 * +----------------------------------------------------------------------
 * | Author: CRMEB Team <admin@crmeb.com>
 * +----------------------------------------------------------------------
 */
@Data
@Service
@SuppressWarnings("all")
public class OrderPayServiceImpl implements OrderPayService {
    private static final Logger logger = LoggerFactory.getLogger(OrderPayServiceImpl.class);

    @Autowired
    private SystemUserLevelService systemUserLevelService;

    @Autowired
    private StoreOrderService storeOrderService;

    @Autowired
    private StoreOrderStatusService storeOrderStatusService;

    @Autowired
    private StoreOrderInfoService storeOrderInfoService;

    @Lazy
    @Autowired
    private WeChatPayService weChatPayService;

    @Autowired
    private TemplateMessageService templateMessageService;

    @Autowired
    private UserBillService userBillService;

    @Lazy
    @Autowired
    private SmsService smsService;

    @Autowired
    private UserService userService;

    @Autowired
    private StoreProductCouponService storeProductCouponService;

    @Autowired
    private StoreCouponUserService storeCouponUserService;

    @Autowired
    private OrderUtils orderUtils;

    //订单类
    private StoreOrder order;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private StoreProductService storeProductService;

    @Autowired
    private UserLevelService userLevelService;

    @Autowired
    private UserBrokerageRecordService userBrokerageRecordService;

    @Autowired
    private StoreCouponService storeCouponService;

    @Autowired
    private SystemAdminService systemAdminService;

    @Autowired
    private UserTokenService userTokenService;

    @Autowired
    private UserIntegralRecordService userIntegralRecordService;

    @Autowired
    private StoreProductAttrValueService storeProductAttrValueService;

    @Autowired
    private WechatNewService wechatNewService;

    @Autowired
    private UserExperienceRecordService userExperienceRecordService;

    @Autowired
    private YlyPrintService ylyPrintService;

    @Autowired
    private SystemNotificationService systemNotificationService;

    @Autowired
    private SmsTemplateService smsTemplateService;

    @Autowired
    private UserIntegralDetailService userIntegralDetailService;  //用户积分详情服务

    @Autowired
    private UserIntegralService userIntegralService;

    @Autowired
    private IntegralUtil integralUtil;

    @Autowired
    private IntegralParameterService integralParameterService;  //积分参数服务

    /**
     * 支付成功处理
     *
     * @param storeOrder 订单
     * @return
     */
    @Override
    @Transactional
    public Boolean paySuccess(StoreOrder storeOrder) {
        // 获取消费者
        User user = userService.getById(storeOrder.getUid());

        // 获取消费者的积分表
        UserIntegral userIntegral = userIntegralService.getById(storeOrder.getUid());

        // 更新用户下单数量
        Integer payCount = user.getPayCount();

        // 如果是首单的话将用户的等级变为消费商
        // 判断是否为首单
        boolean isFirstPush = false;
        boolean isCommonPush = true;
        if (NumberUtil.equals(BigDecimal.valueOf(payCount), BigDecimal.ZERO)) {
            isFirstPush = true;
            user.setLevel(SysLevelConstants.LEVEL_CONSUMER);
        }
        user.setPayCount(payCount + 1);

        // 记录该用户的消费总金额
        user.setNowMoney(user.getNowMoney().add(storeOrder.getPayPrice()));

        // 确定用户完成此单后推荐人的等级
        User spreader = userService.getById(user.getSpreadUid());
        if (!ObjectUtil.isEmpty(spreader)) {
            spreader.setLevel(dealLevel(spreader));
            userService.updateById(spreader);
            // 处理订单分配问题
            //assignmentMoney(storeOrder);
            // 处理分享人的余额(当有分享人时才执行分享人的余额操作)
            dealLinkIdBalance(storeOrder, IntegralDetailConstants.INTEGRAL_TYPE_BALANCE, IntegralDetailConstants.CHANGE_TYPE_ADD, isFirstPush, isCommonPush);
        }
        // 用户信息变更
        userService.updateById(user);

        // 绿色积分处理 逻辑已经实现没问题
        dealGreen(storeOrder, userIntegral, IntegralDetailConstants.INTEGRAL_TYPE_GREEN, IntegralDetailConstants.CHANGE_TYPE_ADD);

        // 增值积分处理 逻辑已经实现没问题
        dealValueAdd(storeOrder, userIntegral, IntegralDetailConstants.INTEGRAL_TYPE_VALUE_ADD, IntegralDetailConstants.CHANGE_TYPE_ADD);

        // 贡献值处理
        dealContribution(storeOrder, userIntegral, IntegralDetailConstants.INTEGRAL_TYPE_CONTRIBUTION, IntegralDetailConstants.CHANGE_TYPE_ADD, isFirstPush);

        userIntegralService.updateById(userIntegral);
        userIntegralService.operationValueAddIntegralFreeze(userIntegral.getUid(), userIntegral.getValueAddIntegral().subtract(storeOrder.getPayPrice()), userIntegral.getValueAddIntegralFreeze(), IntegralDetailConstants.CHANGE_TYPE_ADD);


        /* if (execute) {
            try {
                SystemNotification payNotification = systemNotificationService.getByMark(NotifyConstants.PAY_SUCCESS_MARK);
                // 发送短信
                if (StrUtil.isNotBlank(user.getPhone()) && payNotification.getIsSms().equals(1)) {
                    SmsTemplate smsTemplate = smsTemplateService.getDetail(payNotification.getSmsId());
                    smsService.sendPaySuccess(user.getPhone(), storeOrder.getOrderId(), storeOrder.getPayPrice(), Integer.valueOf(smsTemplate.getTempId()));
                }

                // 发送用户支付成功管理员提醒短信
                SystemNotification payAdminNotification = systemNotificationService.getByMark(NotifyConstants.PAY_SUCCESS_ADMIN_MARK);
                if (payAdminNotification.getIsSms().equals(1)) {
                    // 查询可已发送短信的管理员
                    List<SystemAdmin> systemAdminList = systemAdminService.findIsSmsList();
                    if (CollUtil.isNotEmpty(systemAdminList)) {
                        SmsTemplate smsTemplate = smsTemplateService.getDetail(payAdminNotification.getSmsId());
                        // 发送短信
                        systemAdminList.forEach(admin -> {
                            smsService.sendOrderPaySuccessNotice(admin.getPhone(), storeOrder.getOrderId(), admin.getRealName(), Integer.valueOf(smsTemplate.getTempId()));
                        });
                    }
                }

                if (payNotification.getIsWechat().equals(1) || payNotification.getIsRoutine().equals(1)) {
                    //下发模板通知
                    pushMessageOrder(storeOrder, user, payNotification);
                }

                // 购买成功后根据配置送优惠券
                //autoSendCoupons(storeOrder);

                // 根据配置 打印小票
                ylyPrintService.YlyPrint(storeOrder.getOrderId(), true);

            } catch (Exception e) {
                e.printStackTrace();
                logger.error("短信、模板通知、优惠券或打印小票异常");
            }
        } */
        //订单日志
        Boolean log = storeOrderStatusService.createLog(storeOrder.getId(), Constants.ORDER_LOG_PAY_SUCCESS, Constants.ORDER_LOG_MESSAGE_PAY_SUCCESS);
        return log;
    }

    public void addLinkIdContributionByShare(StoreOrder storeOrder, UserIntegral userIntegral) {
        BigDecimal pv = getPv(storeOrder);
        BigDecimal ContributionChangeValue = integralUtil.consumeTransInContributionByShare(storeOrder.getPayPrice(), pv);
        userIntegralService.operationContributionIntegral(userIntegral.getUid(), ContributionChangeValue, userIntegral.getContributionIntegral(), IntegralDetailConstants.CHANGE_TYPE_ADD);
        // 生成明细
        BigDecimal remainder = userIntegral.getContributionIntegral().add(ContributionChangeValue);
        String reason = StrUtil.format("增加了{}" + IntegralDetailConstants.INTEGRAL_TYPE_CONTRIBUTION + "：分享消费奖励", ContributionChangeValue);
        UserIntegralDetail contributionDetail = integralUtil.createIntegralDetail(userIntegral.getUid(), IntegralDetailConstants.INTEGRAL_TYPE_CONTRIBUTION, IntegralDetailConstants.CHANGE_TYPE_ADD, ContributionChangeValue, reason, remainder);
        userIntegralDetailService.save(contributionDetail);
    }

    /**
     * 获取PV值
     *
     * @param storeOrder
     * @return
     */
    public BigDecimal getPv(StoreOrder storeOrder) {
        StoreOrderInfoOldVo storeOrderInfo = storeOrderInfoService.getOrderListByOrderId(storeOrder.getId()).get(0);
        StoreProductResponse product = storeProductService.getByProductId(storeOrderInfo.getProductId());
        // 为零处理
        BigDecimal pv = product.getPv();
        return pv;
    }

    /**
     * 同比减少贡献值
     *
     * @param userIntegral
     * @param ratio
     * @param isZero
     */
    @Transactional
    public void decLinkIdContribution(BigDecimal beforeValueAddIntegral, UserIntegral userIntegral, boolean isZero) {
        // 获取贡献值
        BigDecimal contributionIntegral = userIntegral.getContributionIntegral();

        // 计算出同步需要减少后的贡献值
        BigDecimal afterContribution = beforeValueAddIntegral.divide(BigDecimal.valueOf(10), 2, RoundingMode.HALF_UP);

        // 贡献值与增值积分同时减少
        userIntegralService.operationContributionIntegral(userIntegral.getUid(), afterContribution, userIntegral.getContributionIntegral(), IntegralDetailConstants.CHANGE_TYPE_DEC);
        BigDecimal remainder = userIntegral.getContributionIntegral().subtract(afterContribution);
        userIntegral.setContributionIntegral(userIntegral.getContributionIntegral().divide(afterContribution));

        // 生成明细
        String contributionReason = StrUtil.format("扣减了{}" + IntegralDetailConstants.INTEGRAL_TYPE_CONTRIBUTION + "：增值积分减少(同比)", afterContribution);
        integralUtil.saveIntegralDetail(userIntegral.getUid(), IntegralDetailConstants.INTEGRAL_TYPE_CONTRIBUTION, IntegralDetailConstants.CHANGE_TYPE_DEC, afterContribution, contributionReason, remainder);
    }

    /**
     * 处理分享人的余额
     *
     * @param storeOrder   订单
     * @param integralType 积分类型
     * @param changeType   积分操作类型
     * @param isFirstPush  首单
     * @param isCommonPush 复单
     */
    public void dealLinkIdBalance(StoreOrder storeOrder, String integralType, Integer changeType, Boolean isFirstPush, Boolean isCommonPush) {
        // 处理的是分享人的余额  如果是A推荐的B 现在是B下单 那么相当于是对A积分表中的的余额进行操作
        // 分享人的积分对象
        UserIntegral sharerUserIntegral = userIntegralService.getById(storeOrder.getLinkId());

        // 当前订单消费者的积分对象
        UserIntegral currentUserIntegral = userIntegralService.getById(storeOrder.getUid());

        // 分享者（A）原本增值积分小于被分享者（B）的 商品的价格，使用原本的增值积分计算  如果推荐一件产品成功就获得20%的增值积分加速
        // 获取该用户的pv值
        BigDecimal pv = getPv(storeOrder);

        // 通过推荐的人购物时增值积分转余额   余额减增值积分部分
        BigDecimal balanceChangeValue = integralUtil.valueAddTransInBalanceByPush(storeOrder.getPayPrice(), isFirstPush, isCommonPush, pv);

        if (isCommonPush && !isFirstPush){

        }
        // 处理分享人的增值积分
        dealLinkIdValueAdd(storeOrder, sharerUserIntegral, balanceChangeValue, isFirstPush);

        // 生成明细
        String reason = StrUtil.format("增加了{}" + IntegralDetailConstants.INTEGRAL_TYPE_BALANCE + "：增值积分转入(分享)", balanceChangeValue);
        BigDecimal balanceRemainder = sharerUserIntegral.getBalance().add(balanceChangeValue);
        integralUtil.saveIntegralDetail(sharerUserIntegral.getUid(), integralType, IntegralDetailConstants.CHANGE_TYPE_ADD, balanceChangeValue, reason, balanceRemainder);
    }

    /**
     * 处理增值积分
     *
     * @param storeOrder   订单
     * @param userIntegral 用户积分
     * @param integralType 积分类型
     * @param changeType   积分操作类型
     * @return 用户积分详情
     */
    @Transactional
    public void dealConsumerValueAdd(StoreOrder storeOrder, UserIntegral userIntegral, BigDecimal balanceChangeValue, Boolean isFirstPush) {
        boolean isZero = false;
        BigDecimal remainder = userIntegral.getValueAddIntegral(); // 500 B消费了之后 A会获得600的增值积分 A的贡献值会先增加50
        BigDecimal beforeValueAddIntegral = userIntegral.getValueAddIntegral();

        // 如果获取到的增值积分 >= 该用户的增值积分 直接将当前的增值积分变为0
        if (NumberUtil.isGreaterOrEqual(balanceChangeValue, userIntegral.getValueAddIntegral())) {
            // 如果用户开始的增值积分等于0
            if (beforeValueAddIntegral.equals(BigDecimal.ZERO)) {
                // 将获得的增值积分全部冻结
                userIntegral.setValueAddIntegralFreeze(userIntegral.getValueAddIntegral().add(balanceChangeValue));
            } else {
                // 否则冻结多出的部分
                userIntegral.setValueAddIntegralFreeze(userIntegral.getValueAddIntegral().add(balanceChangeValue.subtract(beforeValueAddIntegral)));
            }
            remainder = BigDecimal.ZERO;
        } else {
            // 用户当前的增值积分大于增值积分加速：当前的增值积分减去变化的增值积分
            remainder = remainder.subtract(balanceChangeValue);
        }

        // 如果剩余的增值积分为0
        if (remainder.compareTo(BigDecimal.ZERO) == 0) {
            isZero = true;
        }

        // 获取贡献值
        BigDecimal contributionIntegral = userIntegral.getContributionIntegral();

        // 计算出同步需要减少后的贡献值
        BigDecimal afterContribution = balanceChangeValue.divide(BigDecimal.valueOf(10), 2, RoundingMode.HALF_UP);
        if (NumberUtil.isGreaterOrEqual(afterContribution, userIntegral.getContributionIntegral())) {
            // 贡献值不足的话将获得的增值积分加速全都冻结
            userIntegral.setValueAddIntegralFreeze(userIntegral.getValueAddIntegral().add(balanceChangeValue));
        } else {
            // 贡献值与增值积分同比减少
            userIntegralService.operationContributionIntegral(userIntegral.getUid(), afterContribution, userIntegral.getContributionIntegral(), IntegralDetailConstants.CHANGE_TYPE_DEC);
            userIntegral.setContributionIntegral(userIntegral.getContributionIntegral().subtract(afterContribution));

            // 生成明细
            String contributionReason = StrUtil.format("扣减了{}" + IntegralDetailConstants.INTEGRAL_TYPE_CONTRIBUTION + "：增值积分减少(同比)", afterContribution);
            integralUtil.saveIntegralDetail(userIntegral.getUid(), IntegralDetailConstants.INTEGRAL_TYPE_CONTRIBUTION, IntegralDetailConstants.CHANGE_TYPE_DEC, afterContribution, contributionReason, remainder);

            // 增值积分变化的话余额也需要变化
            userIntegral.setBalance(userIntegral.getBalance().add(balanceChangeValue));
        }

        // 将数据库中的更新
        userIntegral.setValueAddIntegral(remainder);
        userIntegralService.updateById(userIntegral);
    }

    /**
     * 处理分享人增值积分
     *
     * @param storeOrder   订单
     * @param userIntegral 用户积分
     * @param integralType 积分类型
     * @param changeType   积分操作类型
     * @return 用户积分详情
     */
    @Transactional
    public void dealLinkIdValueAdd(StoreOrder storeOrder, UserIntegral userIntegral, BigDecimal balanceChangeValue, Boolean isFirstPush) {
        boolean isZero = false;
        BigDecimal remainder = userIntegral.getValueAddIntegral(); // 500 B消费了之后 A会获得600的增值积分 A的贡献值会先增加50
        BigDecimal beforeValueAddIntegral = userIntegral.getValueAddIntegral();

        // 如果获取到的增值积分 >= 该用户的增值积分 直接将当前的增值积分变为0
        if (NumberUtil.isGreaterOrEqual(balanceChangeValue, userIntegral.getValueAddIntegral())) {
            // 如果用户开始的增值积分等于0
            if (beforeValueAddIntegral.equals(BigDecimal.ZERO)) {
                // 将获得的增值积分全部冻结
                userIntegral.setValueAddIntegralFreeze(balanceChangeValue);
            } else {
                // 否则冻结多出的部分
                userIntegral.setValueAddIntegralFreeze(balanceChangeValue.subtract(beforeValueAddIntegral));
            }
            remainder = BigDecimal.ZERO;
        } else {
            // 用户当前的增值积分大于增值积分加速：当前的增值积分减去变化的增值积分
            remainder = remainder.subtract(balanceChangeValue);
        }

        // 如果剩余的增值积分为0
        if (remainder.compareTo(BigDecimal.ZERO) == 0) {
            isZero = true;
        }

        // 如果是首单就获得5%的贡献值
        BigDecimal contribution = BigDecimal.ZERO;
        if (isFirstPush) {
            // 获取增值积分减少的比率
            IntegralParameter integralParameter = integralParameterService.getIntegralParameter(1);
            BigDecimal firstShareRate = integralParameter.getFirstShare().divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);

            // 获得增值积分
            contribution = firstShareRate.multiply(storeOrder.getPayPrice());

            String nickname = userService.getInfoByUid(storeOrder.getUid()).getNickname();
            //生成积分详情表
            String reason = StrUtil.format(nickname + "消费了{}," + "增加" + contribution + "贡献值", storeOrder.getPayPrice());
            integralUtil.saveIntegralDetail(userIntegral.getUid(), IntegralDetailConstants.INTEGRAL_TYPE_CONTRIBUTION, IntegralDetailConstants.CHANGE_TYPE_ADD, contribution, reason, userIntegral.getContributionIntegral().add(contribution));
            userIntegral.setContributionIntegral(userIntegral.getContributionIntegral().add(contribution));
        }

        // 获取贡献值
        BigDecimal contributionIntegral = userIntegral.getContributionIntegral();

        // 计算出同步需要减少后的贡献值
        BigDecimal afterContribution = balanceChangeValue.divide(BigDecimal.valueOf(10), 2, RoundingMode.HALF_UP);

        if (NumberUtil.isGreaterOrEqual(afterContribution, userIntegral.getContributionIntegral())) {
            // 贡献值不足的话将获得的增值积分加速全都冻结
            userIntegral.setValueAddIntegralFreeze(userIntegral.getValueAddIntegralFreeze().add(balanceChangeValue));
        } else {
            // 贡献值与增值积分同比减少
            userIntegralService.operationContributionIntegral(userIntegral.getUid(), afterContribution, userIntegral.getContributionIntegral(), IntegralDetailConstants.CHANGE_TYPE_DEC);
            userIntegral.setContributionIntegral(userIntegral.getContributionIntegral().subtract(afterContribution));

            // 贡献值变化明细
            String contributionReason = StrUtil.format("扣减了{}" + IntegralDetailConstants.INTEGRAL_TYPE_CONTRIBUTION + "：增值积分减少(同比)", afterContribution);
            integralUtil.saveIntegralDetail(userIntegral.getUid(), IntegralDetailConstants.INTEGRAL_TYPE_CONTRIBUTION, IntegralDetailConstants.CHANGE_TYPE_DEC, afterContribution, contributionReason, remainder);
            userIntegral.setBalance(userIntegral.getBalance().add(balanceChangeValue));

            // 余额变化明细
            String balanceReason = StrUtil.format("增加了{}" + IntegralDetailConstants.INTEGRAL_TYPE_BALANCE + "：增值积分加速", balanceChangeValue);
            integralUtil.saveIntegralDetail(userIntegral.getUid(), IntegralDetailConstants.INTEGRAL_TYPE_BALANCE, IntegralDetailConstants.CHANGE_TYPE_ADD, balanceChangeValue, balanceReason, userIntegral.getBalance());
        }

        // 将数据库中的更新
        userIntegral.setValueAddIntegral(remainder);
        userIntegralService.updateById(userIntegral);
    }

    /**
     * 处理增值积分
     *
     * @param storeOrder   订单
     * @param userIntegral 用户积分
     * @param integralType 积分类型
     * @param changeType   积分操作类型
     * @return 用户积分详情
     */
    public void dealValueAdd(StoreOrder storeOrder, UserIntegral userIntegral, String integralType, Integer changeType) {
        BigDecimal valueAddChangeValue = integralUtil.consumeTransInValueAdd(storeOrder.getPayPrice());
        BigDecimal valueAddRemainder = userIntegral.getValueAddIntegral().add(valueAddChangeValue);
        userIntegral.setValueAddIntegral(valueAddRemainder);
        userIntegral.setValueAddIntegralPrincipal(storeOrder.getPayPrice());
        // 生成明细
        saveOrderDetail(userIntegral, integralType, changeType, valueAddChangeValue, valueAddRemainder);
    }

    /**
     * 处理绿色积分
     *
     * @param storeOrder
     * @param userIntegral
     * @param integralType
     * @param changeType
     * @return
     */
    public void dealGreen(StoreOrder storeOrder, UserIntegral userIntegral, String integralType, Integer changeType) {
        // 绿色积分处理
        BigDecimal greenChangeValue = integralUtil.consumeTransInGreen(storeOrder.getPayPrice());
        userIntegralService.operationGreenIntegral(userIntegral.getUid(), greenChangeValue, userIntegral.getGreenIntegral(), changeType);
        userIntegralService.operationGreenIntegralFreeze(userIntegral.getUid(), greenChangeValue, userIntegral.getGreenIntegralFreeze(), changeType);
        userIntegral.setGreenIntegral(userIntegral.getGreenIntegral().add(greenChangeValue));
        userIntegral.setGreenIntegralFreeze(userIntegral.getGreenIntegralFreeze().add(greenChangeValue));
        // 生成明细
        saveOrderDetail(userIntegral, integralType,changeType, greenChangeValue, userIntegral.getGreenIntegral());
    }

    /**
     * 处理贡献值
     *
     * @param storeOrder
     * @param userIntegral
     * @param integralType
     * @param changeType
     * @return
     */
    public void dealContribution(StoreOrder storeOrder, UserIntegral userIntegral,
                                               String integralType, Integer changeType, Boolean isFirstPush) {
        BigDecimal ContributionChangeValue = integralUtil.consumeTransInContribution(storeOrder.getPayPrice());
        userIntegralService.operationContributionIntegral(userIntegral.getUid(), ContributionChangeValue, userIntegral.getContributionIntegral(), changeType);
        // 贡献值与增值积分同比归零
        // 增值积分
        BigDecimal valueAddIntegral = userIntegral.getValueAddIntegral();

        // 对象的贡献值增加
        userIntegral.setContributionIntegral(userIntegral.getContributionIntegral().add(ContributionChangeValue));

        // 贡献值和增值积分同比归零
        //sameDescFuction(userIntegral, contributionRemainder);
    }

    /**
     * 贡献值和增值积分同比归零
     * @param userIntegral
     * @param contributionRemainder
     */
    private void sameDescFuction(UserIntegral userIntegral, BigDecimal contributionRemainder) {
        if (!NumberUtil.equals(contributionRemainder, BigDecimal.ZERO)) {
            if (!NumberUtil.equals(userIntegral.getValueAddIntegralPrincipal(),BigDecimal.ZERO) || !NumberUtil.equals(userIntegral.getGreenIntegralFreeze(),BigDecimal.ZERO)){
                BigDecimal changeToBalance = userIntegral.getValueAddIntegralFreeze().add(userIntegral.getValueAddIntegralPrincipal());
                userIntegral.setContributionIntegral(BigDecimal.ZERO);
                userIntegral.setValueAddIntegralFreeze(BigDecimal.ZERO);
                userIntegral.setValueAddIntegralPrincipal(BigDecimal.ZERO);
                userIntegral.setValueAddIntegral(userIntegral.getValueAddIntegral().subtract(changeToBalance));
                userIntegral.setBalance(userIntegral.getBalance().add(changeToBalance));
            }
        }
    }

    /**
     * 用户下单成功明细
     * @param userIntegral
     * @param integralType
     * @param changeType
     * @param valueAddChangeValue
     * @param valueAddRemainder
     */
    private void saveOrderDetail(UserIntegral userIntegral, String integralType, Integer changeType, BigDecimal valueAddChangeValue, BigDecimal valueAddRemainder) {
        String reason = StrUtil.format("用户付款成功,增加了{}" + integralType, valueAddChangeValue.doubleValue());
        integralUtil.saveIntegralDetail(userIntegral.getUid(), integralType, changeType, valueAddChangeValue, reason, valueAddRemainder);
    }
    //    -----------------流量--------------------------

    /**
     * 处理等级
     *
     * @param spreader
     * @return
     */
    public Integer dealLevel(User spreader) {
        // 获取用户消费总金额
        BigDecimal groupPayPriceByUid = storeOrderService.getGroupPayPriceByUid(spreader.getUid());
        // 根据推广人uid获取用户自己所在团体（非本人创建）总订单数量
        //Integer saleCover = storeOrderService.getGroupOrderByUid(spreader.getUid());
        // 获取等级列表 按升序排序
        List<SystemUserLevel> levelList = systemUserLevelService.getNotPartnerList();

        // 获取推荐人的等级
        for (SystemUserLevel systemUserLevel : levelList) {
            if (NumberUtil.isGreaterOrEqual(systemUserLevel.getSaleMoney().subtract(groupPayPriceByUid), BigDecimal.ZERO)) {
                return systemUserLevel.getGrade();
            }
        }
        return spreader.getLevel();
    }

    /**
     * 判断是否是大市场
     *
     * @param user
     * @return
     */
    public User judgeBigMarket(User user) {
        //        List<User> allUser = userService.getAllUser();
        List<User> memberList = userService.getMemberListByUid(user.getSpreadUid());
        List<BigDecimal> groupMoney = new ArrayList<>();
        BigDecimal maxMoney = BigDecimal.ZERO;
        Integer uid = 0;
        for (int i = 0; i < memberList.size(); i++) {
            BigDecimal groupSale = storeOrderService.getGroupPayPriceByUid(memberList.get(i).getUid());
            if (groupSale.compareTo(maxMoney) > 0) {
                maxMoney = groupSale;
                uid = memberList.get(i).getUid();
            }
        }
        //        allUser.forEach(user -> {
        //            BigDecimal groupSale = storeOrderService.getGroupPayPriceByUid(user.getUid());
        //            if(groupSale.compareTo(maxMoney.get()) > 0){
        //                maxMoney.set(groupSale);
        //                uid = user.getUid();
        //            }
        //        });
        return userService.getById(uid);
    }

    public void dealDividentBalance(Integer uid, BigDecimal balanceChangeValue) {
        UserIntegral userIntegral = userIntegralService.getById(uid);
        // 添加余额
        userIntegralService.operationBalance(uid, balanceChangeValue, userIntegral.getBalance(), IntegralDetailConstants.CHANGE_TYPE_ADD);
        // 生成明细
        String reason = StrUtil.format("增加了{}" + IntegralDetailConstants.INTEGRAL_TYPE_BALANCE + "：市场分红", balanceChangeValue);
        BigDecimal balanceRemainder = userIntegral.getBalance().add(balanceChangeValue);
        UserIntegralDetail userBalanceDetail = integralUtil.createIntegralDetail(userIntegral.getUid(), IntegralDetailConstants.INTEGRAL_TYPE_BALANCE, IntegralDetailConstants.CHANGE_TYPE_ADD, balanceChangeValue, reason, balanceRemainder);
        userIntegralDetailService.save(userBalanceDetail);
    }

    public List<User> getLowMemberAfterSift(User user) { // 筛选出低于消费者自己等级的成员
        List<User> memberList = userService.getMemberListByUid(user.getSpreadUid()); // 先获取所有成员
        User bigMarket = judgeBigMarket(user);
        Iterator<User> iterator = memberList.iterator();
        while (iterator.hasNext()) {
            User member = iterator.next();
            if (member.getLevel() >= user.getLevel() || member.getLevel() == null || member.equals(bigMarket)) {
                iterator.remove();
            }
        }
        return memberList;
    }

    public List<User> getEqualMemberAfterSift(User user) { // 筛选出等于消费者自己等级的成员
        List<User> memberList = userService.getMemberListByUid(user.getSpreadUid()); // 先获取所有成员
        User bigMarket = judgeBigMarket(user);
        Iterator<User> iterator = memberList.iterator();
        while (iterator.hasNext()) {
            User member = iterator.next();
            if (member.getLevel() != user.getLevel() || member.getLevel() == null || member.equals(bigMarket)) {
                iterator.remove();
            }
        }
        return memberList;
    }

    public List<User> getUpMemberAfterSift(User user) { // 筛选出等级高于消费者自己
        List<User> memberList = userService.getMemberListByUid(user.getSpreadUid()); // 先获取所有成员
        Iterator<User> iterator = memberList.iterator();
        while (iterator.hasNext()) {
            User member = iterator.next();
            if (member.getLevel() <= user.getLevel()) {
                iterator.remove();
            }
        }
        return memberList;
    }


    public void dealUper(User user, BigDecimal payPrice) { // 高于自己等级的
        List<User> memberAfterSift = getUpMemberAfterSift(user);
        if (memberAfterSift.size() == 0) { // 没有低于自己的成员直接结束，防止除数为0的错误
            return;
        }
        memberAfterSift.forEach(member -> { // 处理高于自己成员的获利
            BigDecimal banlanceChangeValue = integralUtil.gradeDividend(user.getLevel(), member.getLevel(), payPrice);
            dealDividentBalance(member.getUid(), banlanceChangeValue);
        });
    }

    public void dealEquals(User user, BigDecimal marketDividend) { // 等于自己等级的
        List<User> memberAfterSift = getEqualMemberAfterSift(user);
        if (memberAfterSift.size() == 0) { // 没有等于自己的成员直接结束，防止除数为0的错误
            return;
        }
        BigDecimal memberDividend = integralUtil.memberDividend(user.getLevel(), marketDividend, memberAfterSift.size());
        memberAfterSift.forEach(member -> { // 处理成员余额
            dealDividentBalance(member.getUid(), memberDividend);
        });
    }


    public void dealLower(User user, BigDecimal marketDividend) { // 低于自己等级的
        List<User> memberAfterSift = getLowMemberAfterSift(user);
        if (memberAfterSift.size() == 0) { // 没有低于自己的成员直接结束，防止除数为0的错误
            return;
        }
        BigDecimal memberDividend = integralUtil.memberDividend(user.getLevel(), marketDividend, memberAfterSift.size());
        memberAfterSift.forEach(member -> { // 处理成员余额
            dealDividentBalance(member.getUid(), memberDividend);
        });
    }


    //    public void dealGradeDiff(User spreader, BigDecimal payPrice) { // 处理高于推广人等级的
    //        List<User> upMember = getUpMemberAfterSift(spreader);
    //        upMember.forEach(member -> { // 处理成员余额
    //            BigDecimal banlanceChangeValue = integralUtil.gradeDividend(spreader.getLevel(), member.getLevel(), payPrice);
    //            dealDividentBalance(spreader.getUid(), banlanceChangeValue);
    //        });
    //
    //    }

    public void dealSaleByGreade(User spreader, BigDecimal payPrice) { // 处理等级在销售额中的获利

    }

    /**
     * 处理订单分红问题
     *
     * @param storeOrder
     */
    public void assignmentMoney(StoreOrder storeOrder) { // 订单分红分配
        User user = userService.getById(storeOrder.getUid());
        User spreader = userService.getById(user.getSpreadUid());
        // 小市场
        BigDecimal marketDividend = integralUtil.marketDividend(spreader.getLevel(), storeOrder.getPayPrice());
        BigDecimal personalDividend = integralUtil.personalDividend(spreader.getLevel(), marketDividend);
        // 处理推广者的等级的销售额的获利
        BigDecimal banlanceChangeValue = integralUtil.saleDividend(spreader.getLevel(), storeOrder);
        dealDividentBalance(spreader.getUid(), banlanceChangeValue);
        // 处理高于消费者等级的
        dealUper(user, storeOrder.getPayPrice());
        // 推广人分红余额处理
        dealDividentBalance(spreader.getUid(), personalDividend);
        // 处理等于自己级别的分红的余额
        dealEquals(user, marketDividend);
    }




    /**
     * 分配佣金
     *
     * @param storeOrder 订单
     * @return List<UserBrokerageRecord>
     */
    private List<UserBrokerageRecord> assignCommission(StoreOrder storeOrder) {
        // 检测商城是否开启分销功能
        String isOpen = systemConfigService.getValueByKey(Constants.CONFIG_KEY_STORE_BROKERAGE_IS_OPEN);
        if (StrUtil.isBlank(isOpen) || "0".equals(isOpen)) {
            return CollUtil.newArrayList();
        }
        //        // 营销产品不参与
        //        if(storeOrder.getCombinationId() > 0 || storeOrder.getSeckillId() > 0 || storeOrder.getBargainId() > 0){
        //            return CollUtil.newArrayList();
        //        }
        // 查找订单所属人信息
        User user = userService.getById(storeOrder.getUid());
        // 当前用户不存在 没有上级 或者 当用用户上级时自己  直接返回
        if (null == user.getSpreadUid() || user.getSpreadUid() < 1 || user.getSpreadUid().equals(storeOrder.getUid())) {
            return CollUtil.newArrayList();
        }
        // 获取参与分佣的人（两级）
        List<MyRecord> spreadRecordList = getSpreadRecordList(user.getSpreadUid());
        if (CollUtil.isEmpty(spreadRecordList)) {
            return CollUtil.newArrayList();
        }
        // 获取佣金冻结期
        String fronzenTime = systemConfigService.getValueByKey(Constants.CONFIG_KEY_STORE_BROKERAGE_EXTRACT_TIME);

        // 生成佣金记录
        List<UserBrokerageRecord> brokerageRecordList = spreadRecordList.stream().map(record -> {
            BigDecimal brokerage = calculateCommission(record, storeOrder.getId());
            UserBrokerageRecord brokerageRecord = new UserBrokerageRecord();
            brokerageRecord.setUid(record.getInt("spreadUid"));
            brokerageRecord.setLinkType(BrokerageRecordConstants.BROKERAGE_RECORD_LINK_TYPE_ORDER);
            brokerageRecord.setType(BrokerageRecordConstants.BROKERAGE_RECORD_TYPE_ADD);
            brokerageRecord.setTitle(BrokerageRecordConstants.BROKERAGE_RECORD_TITLE_ORDER);
            brokerageRecord.setPrice(brokerage);
            brokerageRecord.setMark(StrUtil.format("获得推广佣金，分佣{}", brokerage));
            brokerageRecord.setStatus(BrokerageRecordConstants.BROKERAGE_RECORD_STATUS_CREATE);
            brokerageRecord.setFrozenTime(Integer.valueOf(Optional.ofNullable(fronzenTime).orElse("0")));
            brokerageRecord.setCreateTime(DateUtil.nowDateTime());
            brokerageRecord.setBrokerageLevel(record.getInt("index"));
            return brokerageRecord;
        }).collect(Collectors.toList());

        return brokerageRecordList;
    }

    /**
     * 计算佣金
     *
     * @param record  index-分销级数，spreadUid-分销人
     * @param orderId 订单id
     * @return BigDecimal
     */
    private BigDecimal calculateCommission(MyRecord record, Integer orderId) {
        BigDecimal brokeragePrice = BigDecimal.ZERO;
        // 查询订单详情
        List<StoreOrderInfoOldVo> orderInfoVoList = storeOrderInfoService.getOrderListByOrderId(orderId);
        if (CollUtil.isEmpty(orderInfoVoList)) {
            return brokeragePrice;
        }
        BigDecimal totalBrokerPrice = BigDecimal.ZERO;
        //查询对应等级的分销比例
        Integer index = record.getInt("index");
        String key = "";
        if (index == 1) {
            key = Constants.CONFIG_KEY_STORE_BROKERAGE_RATE_ONE;
        }
        if (index == 2) {
            key = Constants.CONFIG_KEY_STORE_BROKERAGE_RATE_TWO;
        }
        String rate = systemConfigService.getValueByKey(key);
        if (StringUtils.isBlank(rate)) {
            rate = "1";
        }
        //佣金比例整数存储， 例如80， 所以计算的时候要除以 10*10
        BigDecimal rateBigDecimal = brokeragePrice;
        if (StringUtils.isNotBlank(rate)) {
            rateBigDecimal = new BigDecimal(rate).divide(BigDecimal.TEN.multiply(BigDecimal.TEN));
        }

        for (StoreOrderInfoOldVo orderInfoVo : orderInfoVoList) {
            // 先看商品是否有固定分佣
            StoreProductAttrValue attrValue = storeProductAttrValueService.getById(orderInfoVo.getInfo().getAttrValueId());
            if (orderInfoVo.getInfo().getIsSub()) {// 有固定分佣
                if (index == 1) {
                    brokeragePrice = Optional.ofNullable(attrValue.getBrokerage()).orElse(BigDecimal.ZERO);
                }
                if (index == 2) {
                    brokeragePrice = Optional.ofNullable(attrValue.getBrokerageTwo()).orElse(BigDecimal.ZERO);
                }
            } else {// 系统分佣
                if (!rateBigDecimal.equals(BigDecimal.ZERO)) {
                    // 商品没有分销金额, 并且有设置对应等级的分佣比例
                    // 舍入模式向零舍入。
                    if (ObjectUtil.isNotNull(orderInfoVo.getInfo().getVipPrice())) {
                        brokeragePrice = orderInfoVo.getInfo().getVipPrice().multiply(rateBigDecimal).setScale(2, BigDecimal.ROUND_DOWN);
                    } else {
                        brokeragePrice = orderInfoVo.getInfo().getPrice().multiply(rateBigDecimal).setScale(2, BigDecimal.ROUND_DOWN);
                    }
                } else {
                    brokeragePrice = BigDecimal.ZERO;
                }
            }
            // 同规格商品可能有多件
            if (brokeragePrice.compareTo(BigDecimal.ZERO) > 0 && orderInfoVo.getInfo().getPayNum() > 1) {
                brokeragePrice = brokeragePrice.multiply(new BigDecimal(orderInfoVo.getInfo().getPayNum()));
            }
            totalBrokerPrice = totalBrokerPrice.add(brokeragePrice);
        }

        return totalBrokerPrice;
    }

    /**
     * 获取参与分佣人员（两级）
     *
     * @param spreadUid 一级分佣人Uid
     * @return List<MyRecord>
     */
    private List<MyRecord> getSpreadRecordList(Integer spreadUid) {
        List<MyRecord> recordList = CollUtil.newArrayList();

        // 第一级
        User spreadUser = userService.getById(spreadUid);
        if (ObjectUtil.isNull(spreadUser)) {
            return recordList;
        }
        // 判断分销模式
        String model = systemConfigService.getValueByKey(Constants.CONFIG_KEY_STORE_BROKERAGE_MODEL);
        if (StrUtil.isNotBlank(model) && "1".equals(model) && !spreadUser.getIsPromoter()) {
            // 指定分销模式下：不是推广员不参与分销
            return recordList;
        }
        MyRecord firstRecord = new MyRecord();
        firstRecord.set("index", 1);
        firstRecord.set("spreadUid", spreadUid);
        recordList.add(firstRecord);

        // 第二级
        User spreadSpreadUser = userService.getById(spreadUser.getSpreadUid());
        if (ObjectUtil.isNull(spreadSpreadUser)) {
            return recordList;
        }
        if (StrUtil.isNotBlank(model) && "1".equals(model) && !spreadSpreadUser.getIsPromoter()) {
            // 指定分销模式下：不是推广员不参与分销
            return recordList;
        }
        MyRecord secondRecord = new MyRecord();
        secondRecord.set("index", 2);
        secondRecord.set("spreadUid", spreadSpreadUser.getUid());
        recordList.add(secondRecord);
        return recordList;
    }

    //    ----------------------begin-------------

    /**
     * 余额支付
     *
     * @param storeOrder 订单
     * @return Boolean Boolean
     */
    private Boolean greenPay(StoreOrder storeOrder) {

        // 绿色积分扣除
        User user = userService.getById(storeOrder.getUid());
        UserIntegral userIntegral = userIntegralService.getById(user.getUid());

        if (ObjectUtil.isNull(user))
            throw new CrmebException("用户不存在");
        //        BigDecimal shouldPay = integralUtil.premiumOfGreen(storeOrder.getPayPrice()).add(storeOrder.getPayPrice());
        if (userIntegral.getGreenIntegral().compareTo(storeOrder.getPayPrice()) < 0) {
            throw new CrmebException("用户绿色不足");
        }
        storeOrder.setPaid(true);
        storeOrder.setPayTime(DateUtil.nowDateTime());
        Boolean execute = transactionTemplate.execute(e -> {
            // 订单修改
            storeOrderService.updateById(storeOrder);
            // 这里只扣除金额，账单记录在task中处理
            userService.updateNowMoney(user, storeOrder.getPayPrice(), "sub");
            //            --------------------begin------------
            // 这里扣除增值积分
            userIntegralService.operationGreenIntegral(user.getUid(), storeOrder.getPayPrice(), userIntegral.getGreenIntegral(), IntegralDetailConstants.CHANGE_TYPE_DEC);
            // 生成记录
            String reason = StrUtil.format("支付成功，减少了{}" + IntegralDetailConstants.INTEGRAL_TYPE_GREEN, storeOrder.getPayPrice());
            BigDecimal remainder = userIntegral.getGreenIntegral().subtract(storeOrder.getPayPrice());
            UserIntegralDetail integralDetail = integralUtil.createIntegralDetail(userIntegral.getUid(), IntegralDetailConstants.INTEGRAL_TYPE_GREEN, IntegralDetailConstants.CHANGE_TYPE_DEC, storeOrder.getPayPrice(), reason, remainder);
            userIntegralDetailService.save(integralDetail);
            //            ---------------------end--------------
            // 扣除积分
            if (storeOrder.getUseIntegral() > 0) {
                userService.updateIntegral(user, storeOrder.getUseIntegral(), "sub");
            }

            // 添加支付成功redis队列
            redisUtil.lPush(TaskConstants.ORDER_TASK_PAY_SUCCESS_AFTER, storeOrder.getOrderId());


            return Boolean.TRUE;
        });
        if (!execute)
            throw new CrmebException("绿色积分支付订单失败");
        return execute;
    }

    //    --------------------end-----------------

    /**
     * 余额支付
     *
     * @param storeOrder 订单
     * @return Boolean Boolean
     */
    private Boolean yuePay(StoreOrder storeOrder) {

        // 用户余额扣除
        User user = userService.getById(storeOrder.getUid());
        if (ObjectUtil.isNull(user))
            throw new CrmebException("用户不存在");
        if (user.getNowMoney().compareTo(storeOrder.getPayPrice()) < 0) {
            throw new CrmebException("用户余额不足");
        }
        if (user.getIntegral() < storeOrder.getUseIntegral()) {
            throw new CrmebException("用户积分不足");
        }
        storeOrder.setPaid(true);
        storeOrder.setPayTime(DateUtil.nowDateTime());
        Boolean execute = transactionTemplate.execute(e -> {
            // 订单修改
            storeOrderService.updateById(storeOrder);
            // 这里只扣除金额，账单记录在task中处理
            userService.updateNowMoney(user, storeOrder.getPayPrice(), "sub");
            // 扣除积分
            if (storeOrder.getUseIntegral() > 0) {
                userService.updateIntegral(user, storeOrder.getUseIntegral(), "sub");
            }
            // 添加支付成功redis队列
            redisUtil.lPush(TaskConstants.ORDER_TASK_PAY_SUCCESS_AFTER, storeOrder.getOrderId());


            return Boolean.TRUE;
        });
        if (!execute)
            throw new CrmebException("余额支付订单失败");
        return execute;
    }

    /**
     * 订单支付
     *
     * @param orderPayRequest 支付参数
     * @param ip              ip
     * @return OrderPayResultResponse
     * 1.微信支付拉起微信预支付，返回前端调用微信支付参数，在之后需要调用微信支付查询接口
     * 2.余额支付，更改对应信息后，加入支付成功处理task
     */
    @Override
    @Transactional
    public OrderPayResultResponse payment(OrderPayRequest orderPayRequest, String ip) {
        StoreOrder storeOrder = storeOrderService.getByOderId(orderPayRequest.getOrderNo());
        if (ObjectUtil.isNull(storeOrder)) {
            throw new CrmebException("订单不存在");
        }
        if (storeOrder.getIsDel()) {
            throw new CrmebException("订单已被删除");
        }
        if (storeOrder.getPaid()) {
            throw new CrmebException("订单已支付");
        }
        User user = userService.getById(storeOrder.getUid());
        UserIntegral userIntegral = new UserIntegral();
        if (ObjectUtil.isNull(user))
            throw new CrmebException("用户不存在");

        // 判断订单是否还是之前的支付类型
        if (!storeOrder.getPayType().equals(orderPayRequest.getPayType())) {
            // 根据支付类型进行校验,更换支付类型
            storeOrder.setPayType(orderPayRequest.getPayType());
            // 余额支付
            //            if (orderPayRequest.getPayType().equals(PayConstants.PAY_TYPE_YUE)) {
            //                if (user.getNowMoney().compareTo(storeOrder.getPayPrice()) < 0) {
            //                    throw new CrmebException("用户余额不足");
            //                }
            //                storeOrder.setIsChannel(3);
            //            }
            //            ---------------begin -----------
            // 绿色积分支付
            if (orderPayRequest.getPayType().equals(PayConstants.PAY_TYPE_YUE)) {
                //                BigDecimal shouldPay = integralUtil.premiumOfGreen(storeOrder.getPayPrice()).add(storeOrder.getPayPrice());
                if (userIntegral.getGreenIntegral().compareTo(storeOrder.getPayPrice()) < 0) {
                    throw new CrmebException("用户绿色不足");
                }
                storeOrder.setIsChannel(3);
            }
            //            ------------------end---------
            // 微信支付
            if (orderPayRequest.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT)) {
                switch (orderPayRequest.getPayChannel()) {
                    case PayConstants.PAY_CHANNEL_WE_CHAT_H5:// H5
                        storeOrder.setIsChannel(2);
                        break;
                    case PayConstants.PAY_CHANNEL_WE_CHAT_PUBLIC:// 公众号
                        storeOrder.setIsChannel(0);
                        break;
                    case PayConstants.PAY_CHANNEL_WE_CHAT_PROGRAM:// 小程序
                        storeOrder.setIsChannel(1);
                        break;
                }
            }

            boolean changePayType = storeOrderService.updateById(storeOrder);
            if (!changePayType) {
                throw new CrmebException("变更订单支付类型失败!");
            }
        }

        if (user.getIntegral() < storeOrder.getUseIntegral()) {
            throw new CrmebException("用户积分不足");
        }

        OrderPayResultResponse response = new OrderPayResultResponse();
        response.setOrderNo(storeOrder.getOrderId());
        response.setPayType(storeOrder.getPayType());
        // 0元付
        if (storeOrder.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) {
            Boolean aBoolean = yuePay(storeOrder);
            response.setPayType(PayConstants.PAY_TYPE_YUE);
            response.setStatus(aBoolean);
            paySuccess(storeOrder); //////////////////////////
            return response;
        }

        // 微信支付，调用微信预下单，返回拉起微信支付需要的信息
        if (storeOrder.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT)) {
            // 预下单
            Map<String, String> unifiedorder = unifiedorder(storeOrder, ip);
            response.setStatus(true);
            WxPayJsResultVo vo = new WxPayJsResultVo();
            vo.setAppId(unifiedorder.get("appId"));
            vo.setNonceStr(unifiedorder.get("nonceStr"));
            vo.setPackages(unifiedorder.get("package"));
            vo.setSignType(unifiedorder.get("signType"));
            vo.setTimeStamp(unifiedorder.get("timeStamp"));
            vo.setPaySign(unifiedorder.get("paySign"));
            if (storeOrder.getIsChannel() == 2) {
                vo.setMwebUrl(unifiedorder.get("mweb_url"));
                response.setPayType(PayConstants.PAY_CHANNEL_WE_CHAT_H5);
            }
            if (storeOrder.getIsChannel() == 4 || storeOrder.getIsChannel() == 5) {
                vo.setPartnerid(unifiedorder.get("partnerid"));
            }
            // 更新商户订单号
            storeOrder.setOutTradeNo(unifiedorder.get("outTradeNo"));
            storeOrderService.updateById(storeOrder);
            response.setJsConfig(vo);
            paySuccess(storeOrder);///////////////////////////
            return response;
        }
        //        // 余额支付
        //        if (storeOrder.getPayType().equals(PayConstants.PAY_TYPE_YUE)) {
        //            Boolean yueBoolean = yuePay(storeOrder);
        //            response.setStatus(yueBoolean);
        //            paySuccess(storeOrder);//////////////////////////////////////
        //            return response;
        //        }
        // 绿色积分支付
        if (storeOrder.getPayType().equals(PayConstants.PAY_TYPE_YUE)) {
            Boolean greenBoolean = greenPay(storeOrder);
            response.setStatus(greenBoolean);
            paySuccess(storeOrder);//////////////////////////////////////
            return response;
        }

        if (storeOrder.getPayType().equals(PayConstants.PAY_TYPE_OFFLINE)) {
            throw new CrmebException("暂时不支持线下支付");
        }
        response.setStatus(false);
        return response;
    }

    /**
     * 预下单
     *
     * @param storeOrder 订单
     * @param ip         ip
     * @return 预下单返回对象
     */
    private Map<String, String> unifiedorder(StoreOrder storeOrder, String ip) {
        // 获取用户openId
        // 根据订单支付类型来判断获取公众号openId还是小程序openId
        UserToken userToken = new UserToken();
        if (storeOrder.getIsChannel() == 0) {// 公众号
            userToken = userTokenService.getTokenByUserId(storeOrder.getUid(), 1);
        }
        if (storeOrder.getIsChannel() == 1) {// 小程序
            userToken = userTokenService.getTokenByUserId(storeOrder.getUid(), 2);
        }
        if (storeOrder.getIsChannel() == 2) {// H5
            userToken.setToken("");
        }
        if (ObjectUtil.isNull(userToken)) {
            throw new CrmebException("该用户没有openId");
        }

        // 获取appid、mch_id
        // 微信签名key
        String appId = "";
        String mchId = "";
        String signKey = "";
        if (storeOrder.getIsChannel() == 0) {// 公众号
            appId = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_PAY_WE_CHAT_APP_ID);
            mchId = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_PAY_WE_CHAT_MCH_ID);
            signKey = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_PAY_WE_CHAT_APP_KEY);
        }
        if (storeOrder.getIsChannel() == 1) {// 小程序
            appId = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_PAY_ROUTINE_APP_ID);
            mchId = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_PAY_ROUTINE_MCH_ID);
            signKey = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_PAY_ROUTINE_APP_KEY);
        }
        if (storeOrder.getIsChannel() == 2) {// H5,使用公众号的
            appId = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_PAY_WE_CHAT_APP_ID);
            mchId = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_PAY_WE_CHAT_MCH_ID);
            signKey = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_PAY_WE_CHAT_APP_KEY);
        }
        // 获取微信预下单对象
        CreateOrderRequestVo unifiedorderVo = getUnifiedorderVo(storeOrder, userToken.getToken(), ip, appId, mchId, signKey);
        // 预下单（统一下单）
        CreateOrderResponseVo responseVo = wechatNewService.payUnifiedorder(unifiedorderVo);
        // 组装前端预下单参数
        Map<String, String> map = new HashMap<>();
        map.put("appId", unifiedorderVo.getAppid());
        map.put("nonceStr", unifiedorderVo.getAppid());
        map.put("package", "prepay_id=".concat(responseVo.getPrepayId()));
        map.put("signType", unifiedorderVo.getSign_type());
        Long currentTimestamp = WxPayUtil.getCurrentTimestamp();
        map.put("timeStamp", Long.toString(currentTimestamp));
        String paySign = WxPayUtil.getSign(map, signKey);
        map.put("paySign", paySign);
        map.put("prepayId", responseVo.getPrepayId());
        map.put("prepayTime", DateUtil.nowDateTimeStr());
        map.put("outTradeNo", unifiedorderVo.getOut_trade_no());
        if (storeOrder.getIsChannel() == 2) {
            map.put("mweb_url", responseVo.getMWebUrl());
        }
        return map;
    }

    /**
     * 获取微信预下单对象
     *
     * @return 微信预下单对象
     */
    private CreateOrderRequestVo getUnifiedorderVo(StoreOrder storeOrder, String openid, String ip, String appId, String mchId, String signKey) {

        // 获取域名
        String domain = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_SITE_URL);
        String apiDomain = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_API_URL);

        AttachVo attachVo = new AttachVo(Constants.SERVICE_PAY_TYPE_ORDER, storeOrder.getUid());
        CreateOrderRequestVo vo = new CreateOrderRequestVo();

        vo.setAppid(appId);
        vo.setMch_id(mchId);
        vo.setNonce_str(WxPayUtil.getNonceStr());
        vo.setSign_type(PayConstants.WX_PAY_SIGN_TYPE_MD5);
        String siteName = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_SITE_NAME);
        // 因商品名称在微信侧超长更换为网站名称
        vo.setBody(siteName);
        vo.setAttach(JSONObject.toJSONString(attachVo));
        vo.setOut_trade_no(CrmebUtil.getOrderNo("wxNo"));
        // 订单中使用的是BigDecimal,这里要转为Integer类型
        vo.setTotal_fee(storeOrder.getPayPrice().multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).intValue());
        vo.setSpbill_create_ip(ip);
        vo.setNotify_url(apiDomain + PayConstants.WX_PAY_NOTIFY_API_URI);
        vo.setTrade_type(PayConstants.WX_PAY_TRADE_TYPE_JS);
        vo.setOpenid(openid);
        if (storeOrder.getIsChannel() == 2) {// H5
            vo.setTrade_type(PayConstants.WX_PAY_TRADE_TYPE_H5);
            vo.setOpenid(null);
        }
        CreateOrderH5SceneInfoVo createOrderH5SceneInfoVo = new CreateOrderH5SceneInfoVo(new CreateOrderH5SceneInfoDetailVo(domain, systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_SITE_NAME)));
        vo.setScene_info(JSONObject.toJSONString(createOrderH5SceneInfoVo));
        String sign = WxPayUtil.getSign(vo, signKey);
        vo.setSign(sign);
        return vo;
    }

    private UserIntegralRecord integralRecordSubInit(StoreOrder storeOrder, User user) {
        UserIntegralRecord integralRecord = new UserIntegralRecord();
        integralRecord.setUid(storeOrder.getUid());
        integralRecord.setLinkId(storeOrder.getOrderId());
        integralRecord.setLinkType(IntegralRecordConstants.INTEGRAL_RECORD_LINK_TYPE_ORDER);
        integralRecord.setType(IntegralRecordConstants.INTEGRAL_RECORD_TYPE_SUB);
        integralRecord.setTitle(IntegralRecordConstants.BROKERAGE_RECORD_TITLE_ORDER);
        integralRecord.setIntegral(storeOrder.getUseIntegral());
        integralRecord.setBalance(user.getIntegral());
        integralRecord.setMark(StrUtil.format("订单支付抵扣{}积分购买商品", storeOrder.getUseIntegral()));
        integralRecord.setStatus(IntegralRecordConstants.INTEGRAL_RECORD_STATUS_COMPLETE);
        return integralRecord;
    }

    private UserBill userBillInit(StoreOrder order, User user) {
        UserBill userBill = new UserBill();
        userBill.setPm(0);
        userBill.setUid(order.getUid());
        userBill.setLinkId(order.getId().toString());
        userBill.setTitle("购买商品");
        userBill.setCategory(Constants.USER_BILL_CATEGORY_MONEY);
        userBill.setType(Constants.USER_BILL_TYPE_PAY_ORDER);
        userBill.setNumber(order.getPayPrice());
        userBill.setBalance(user.getNowMoney());
        userBill.setMark("支付" + order.getPayPrice() + "元购买商品");
        return userBill;
    }

    /**
     * 经验添加记录
     */
    private UserExperienceRecord experienceRecordInit(StoreOrder storeOrder, Integer balance, Integer experience) {
        UserExperienceRecord record = new UserExperienceRecord();
        record.setUid(storeOrder.getUid());
        record.setLinkId(storeOrder.getOrderId());
        record.setLinkType(ExperienceRecordConstants.EXPERIENCE_RECORD_LINK_TYPE_ORDER);
        record.setType(ExperienceRecordConstants.EXPERIENCE_RECORD_TYPE_ADD);
        record.setTitle(ExperienceRecordConstants.EXPERIENCE_RECORD_TITLE_ORDER);
        record.setExperience(experience);
        record.setBalance(balance);
        record.setMark("用户付款成功增加" + experience + "经验");
        record.setCreateTime(cn.hutool.core.date.DateUtil.date());
        return record;
    }

    /**
     * 积分添加记录
     *
     * @return UserIntegralRecord
     */
    public UserIntegralDetail integralDetailInit(Integer uid, String integralType, BigDecimal value, BigDecimal remainder) {
        String reason = StrUtil.format("用户付款成功,增加了{}" + integralType, value);
        return integralUtil.createIntegralDetail(uid, integralType, IntegralDetailConstants.CHANGE_TYPE_ADD, value, reason, remainder);
    }

    /* private UserIntegralRecord integralRecordInit(StoreOrder storeOrder, Integer balance, Integer integral, String type) {
        UserIntegralRecord integralRecord = new UserIntegralRecord();
        integralRecord.setUid(storeOrder.getUid());
        integralRecord.setLinkId(storeOrder.getOrderId());
        integralRecord.setLinkType(IntegralRecordConstants.INTEGRAL_RECORD_LINK_TYPE_ORDER);
        integralRecord.setType(IntegralRecordConstants.INTEGRAL_RECORD_TYPE_ADD);
        integralRecord.setTitle(IntegralRecordConstants.BROKERAGE_RECORD_TITLE_ORDER);
        integralRecord.setIntegral(integral);
        integralRecord.setBalance(balance);
        if ("order".equals(type)) {
            integralRecord.setMark(StrUtil.format("用户付款成功,订单增加{}积分", integral));
        }
        if ("product".equals(type)) {
            integralRecord.setMark(StrUtil.format("用户付款成功,商品增加{}积分", integral));
        }
        integralRecord.setStatus(IntegralRecordConstants.INTEGRAL_RECORD_STATUS_CREATE);
        // 获取积分冻结期
        String fronzenTime = systemConfigService.getValueByKey(Constants.CONFIG_KEY_STORE_INTEGRAL_EXTRACT_TIME);
        integralRecord.setFrozenTime(Integer.valueOf(Optional.ofNullable(fronzenTime).orElse("0")));
        integralRecord.setCreateTime(DateUtil.nowDateTime());
        return integralRecord;
    } */

    /**
     * 发送消息通知
     * 根据用户类型发送
     * 公众号模板消息
     * 小程序订阅消息
     */
    private void pushMessageOrder(StoreOrder storeOrder, User user, SystemNotification payNotification) {
        if (storeOrder.getIsChannel().equals(2)) {// H5
            return;
        }
        UserToken userToken;
        HashMap<String, String> temMap = new HashMap<>();
        if (!storeOrder.getPayType().equals(Constants.PAY_TYPE_WE_CHAT)) {
            return;
        }
        // 公众号
        if (storeOrder.getIsChannel().equals(Constants.ORDER_PAY_CHANNEL_PUBLIC) && payNotification.getIsWechat().equals(1)) {
            userToken = userTokenService.getTokenByUserId(user.getUid(), UserConstants.USER_TOKEN_TYPE_WECHAT);
            if (ObjectUtil.isNull(userToken)) {
                return;
            }
            // 发送微信模板消息
            temMap.put(Constants.WE_CHAT_TEMP_KEY_FIRST, "您的订单已支付成功！");
            temMap.put("keyword1", storeOrder.getPayPrice().toString());
            temMap.put("keyword2", storeOrder.getOrderId());
            temMap.put(Constants.WE_CHAT_TEMP_KEY_END, "欢迎下次再来！");
            templateMessageService.pushTemplateMessage(payNotification.getWechatId(), temMap, userToken.getToken());
            return;
        }
        if (storeOrder.getIsChannel().equals(Constants.ORDER_PAY_CHANNEL_PROGRAM) && payNotification.getIsRoutine().equals(1)) {
            // 小程序发送订阅消息
            userToken = userTokenService.getTokenByUserId(user.getUid(), UserConstants.USER_TOKEN_TYPE_ROUTINE);
            if (ObjectUtil.isNull(userToken)) {
                return;
            }
            // 组装数据
            //            temMap.put("character_string1", storeOrder.getOrderId());
            //            temMap.put("amount2", storeOrder.getPayPrice().toString() + "元");
            //            temMap.put("thing7", "您的订单已支付成功");
            temMap.put("character_string3", storeOrder.getOrderId());
            temMap.put("amount9", storeOrder.getPayPrice().toString() + "元");
            temMap.put("thing6", "您的订单已支付成功");
            templateMessageService.pushMiniTemplateMessage(payNotification.getRoutineId(), temMap, userToken.getToken());
        }
    }

    /**
     * 商品购买后根据配置送券
     */
    private void autoSendCoupons(StoreOrder storeOrder) {
        // 根据订单详情获取商品信息
        List<StoreOrderInfoOldVo> orders = storeOrderInfoService.getOrderListByOrderId(storeOrder.getId());
        if (null == orders) {
            return;
        }
        List<StoreCouponUser> couponUserList = CollUtil.newArrayList();
        Map<Integer, Boolean> couponMap = CollUtil.newHashMap();
        for (StoreOrderInfoOldVo order : orders) {
            List<StoreProductCoupon> couponsForGiveUser = storeProductCouponService.getListByProductId(order.getProductId());
            for (int i = 0; i < couponsForGiveUser.size(); ) {
                StoreProductCoupon storeProductCoupon = couponsForGiveUser.get(i);
                MyRecord record = storeCouponUserService.paySuccessGiveAway(storeProductCoupon.getIssueCouponId(), storeOrder.getUid());
                if ("fail".equals(record.getStr("status"))) {
                    logger.error(StrUtil.format("支付成功领取优惠券失败，失败原因：{}", record.getStr("errMsg")));
                    couponsForGiveUser.remove(i);
                    continue;
                }

                StoreCouponUser storeCouponUser = record.get("storeCouponUser");
                couponUserList.add(storeCouponUser);
                couponMap.put(storeCouponUser.getCouponId(), record.getBoolean("isLimited"));
                i++;
            }
        }

        Boolean execute = transactionTemplate.execute(e -> {
            if (CollUtil.isNotEmpty(couponUserList)) {
                storeCouponUserService.saveBatch(couponUserList);
                couponUserList.forEach(i -> storeCouponService.deduction(i.getCouponId(), 1, couponMap.get(i.getCouponId())));
            }
            return Boolean.TRUE;
        });
        if (!execute) {
            logger.error(StrUtil.format("支付成功领取优惠券，更新数据库失败，订单编号：{}", storeOrder.getOrderId()));
        }
    }
}
